const crypto = require('crypto');

class ByfuidGenerator {
  constructor() {
    this.encodingChars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
  }

  /**
   * 生成用户数据
   * @param {number} length - 数据长度，必须为12
   * @returns {string}
   */
  generateUserData(length = 12) {
    if (length !== 12) {
      throw new Error('用户自由数据必须为12字符');
    }

    const chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
    let result = '';
    for (let i = 0; i < length; i++) {
      result += chars.charAt(Math.floor(Math.random() * chars.length));
    }
    return result;
  }

  /**
   * 生成时间戳
   * @returns {string}
   */
  generateTimestamp() {
    const timestamp = Date.now().toString();
    if (timestamp.length < 13) {
      return timestamp.padStart(13, '0');
    } else if (timestamp.length > 13) {
      return timestamp.substring(0, 13);
    }
    return timestamp;
  }

  /**
   * 生成校验和
   * @param {string} data - 要校验的数据
   * @param {number} length - 校验和长度，必须为24
   * @returns {string}
   */
  generateChecksum(data, length = 24) {
    if (length !== 24) {
      throw new Error('数据校验数据必须为24字符');
    }

    const hash = crypto.createHash('sha256');
    hash.update(data);
    return hash.digest('hex').substring(0, length);
  }

  /**
   * 生成自定义数据
   * @param {number} length - 数据长度，必须为201
   * @param {string} [customInput] - 自定义输入
   * @returns {string}
   */
  generateCustomData(length = 201, customInput = null) {
    if (length !== 201) {
      throw new Error('自定义数据必须为201字符');
    }

    if (customInput) {
      // 去除输入中的换行符
      const cleanedInput = this.removeNewlines(customInput);
      const inputLength = cleanedInput.length;

      if (inputLength > length) {
        return cleanedInput.substring(0, length);
      } else if (inputLength < length) {
        let result = cleanedInput;
        const chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!@#$%^&*()你好世界欢迎编程开发技术数据验证安全加密';
        
        while (result.length < length) {
          result += chars.charAt(Math.floor(Math.random() * chars.length));
        }
        return result;
      }
      return cleanedInput;
    } else {
      const chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!@#$%^&*()你好世界欢迎编程开发技术数据验证安全加密';
      let result = '';
      for (let i = 0; i < length; i++) {
        result += chars.charAt(Math.floor(Math.random() * chars.length));
      }
      return result;
    }
  }

  /**
   * 自定义编码
   * @param {string} data - 要编码的数据
   * @param {string} password - 密码
   * @returns {string}
   */
  customEncode(data, password) {
    const encoded = [];
    const passwordLen = password.length;

    for (let i = 0; i < data.length; i++) {
      const dataChar = data.charCodeAt(i);
      const passwordChar = password.charCodeAt(i % passwordLen);
      encoded.push(String.fromCharCode(dataChar ^ passwordChar));
    }

    return encoded.join('');
  }

  /**
   * 去除字符串中的所有换行符
   * @param {string} text - 输入文本
   * @returns {string}
   */
  removeNewlines(text) {
    return text.replace(/\n|\r/g, '');
  }

  /**
   * 生成 BYFUID
   * @param {string} [userInput] - 用户输入数据
   * @param {string} [customInput] - 自定义输入数据
   * @returns {string}
   */
  generateByfuid(userInput = null, customInput = null) {
    // 用户数据
    let userData;
    if (userInput) {
      // 去除用户输入中的换行符
      const cleanedInput = this.removeNewlines(userInput);
      if (cleanedInput.length !== 12) {
        throw new Error('用户自由数据必须为12字符');
      }
      userData = cleanedInput;
    } else {
      userData = this.generateUserData();
    }

    // 自定义数据
    const customData = this.generateCustomData(201, customInput);

    // 时间戳
    const timestamp = this.generateTimestamp();

    // 校验和
    const partialData = userData + customData + timestamp;
    const checksum = this.generateChecksum(partialData);

    // 组装
    const rawData = userData + customData + timestamp + checksum;
    const cleanedData = rawData.replace(/ /g, '+');

    // 编码
    const base64Encoded = Buffer.from(cleanedData).toString('base64');
    const customEncoded = this.customEncode(base64Encoded, timestamp);
    const finalBase64 = Buffer.from(customEncoded).toString('base64');

    // 去除所有换行符并调整长度
    let finalByfuid = this.removeNewlines(finalBase64);

    if (finalByfuid.length > 512) {
      return finalByfuid.substring(0, 512);
    } else if (finalByfuid.length < 512) {
      return finalByfuid + '+'.repeat(512 - finalByfuid.length);
    }
    return finalByfuid;
  }

  /**
   * 验证 BYFUID 长度
   * @param {string} byfuid - BYFUID 字符串
   * @returns {boolean}
   */
  validateByfuidLength(byfuid) {
    return byfuid.length === 512;
  }
}

module.exports = ByfuidGenerator;